use serde_json::{Map, Value};
use snafu::ensure_whatever;

#[derive(Debug, Clone)]
pub struct FieldOrder {
    pub names: Vec<String>,
    pub omit_nulls: bool,
}

pub fn materialize_payload(item: &Value, spec: &FieldOrder) -> crate::Result<Value> {
    match item {
        Value::Array(arr) => {
            ensure_whatever!(
                arr.len() == spec.names.len(),
                "positional item length {} != fields length {}",
                arr.len(),
                spec.names.len()
            );

            let mut obj = Map::with_capacity(arr.len());
            for (i, name) in spec.names.iter().enumerate() {
                let v = &arr[i];
                if spec.omit_nulls && v.is_null() {
                    continue;
                }
                obj.insert(name.clone(), v.clone());
            }

            Ok(Value::Object(obj))
        }
        Value::Object(map) => {
            if !spec.omit_nulls {
                return Ok(item.clone());
            }
            let mut obj = Map::with_capacity(map.len());
            for (k, v) in map {
                if v.is_null() {
                    continue;
                }
                obj.insert(k.clone(), v.clone());
            }

            Ok(Value::Object(obj))
        }
        _ => unimplemented!(),
    }
}
